package com.second.app.superthread;

import java.util.concurrent.CountDownLatch;

/**
 * @Author GYZ
 * @Date 2024/1/5
 * <pre>
 *  countDowmLatch:门闩，
 *  也就是门锁的功能。所以当门没有打开时，N个人是不能进入屋内的
 *  也就是N个线程是不能继续向下运行的，支持这样的特性可以控制线程执行任务的时机。使线程以“组团”的方式一起执行任务
 *  该类：也是一个同步功能的辅助类，使用效果是给一个定数，当使用这个countdownLatch类的线程判断计数不为0时，则呈“wait”状态，如果是0时继续运行。
 *    实现等待和继续运行的效果分别使用await和countDown方法来进行，调用await方法时判断计数是否为0，如果不为0则呈等待状态。
 *    其他线程可以调用countDown方法将计数减1，当计数减到0时，则呈等待的线程继续运行。而方法getCount就是获得当前的计数个数。
 *
 *    计数无法被重置，如果需要重置计数，考虑使用CyclicBarrier类
 * </pre>
 */
public class CountDownLatchDemo {

    /**
     * 10个计数 线程a执行循环，每循环一次,计数-1；此时主线程需等待计数为0，才可以打印输出main end --
     * @param args
     */
    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(10);
        Thread a = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    System.out.println("A");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    countDownLatch.countDown();
                }
            }
        });
        a.start();
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("main end --");
    }
}


/**
 * 以下2个案例，模拟10个运动员到现场准备就绪
 */
class RunnerSign{
    private final CountDownLatch  countDownLatch;

    public RunnerSign(CountDownLatch  countDownLatch){
        this.countDownLatch =countDownLatch;
    }
    public void sign(){
        try {
            Thread.sleep(5000);
            System.out.println("运动员"+Thread.currentThread().getName()+"，已经到现场了！");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            countDownLatch.countDown();
        }
    }
}
class RunDemo{
    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(10);

        RunnerSign runnerSign = new RunnerSign(countDownLatch);
        for (long l = 0; l < countDownLatch.getCount(); l++) {
            new Thread(() -> {
                runnerSign.sign();
            }).start();
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("所有运动员都已经到现场了！");
    }
}
class RunThread extends Thread{
    private final CountDownLatch  countDownLatch;

    public RunThread(CountDownLatch  countDownLatch){
        this.countDownLatch =countDownLatch;
    }
    public void run(){
        try {
            Thread.sleep(10000);
            System.out.println("运动员"+Thread.currentThread().getName()+"，已经到现场了！");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            countDownLatch.countDown();
        }
    }
}

class Run1Demo{
    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(10);

        RunThread[] runnerSign = new RunThread[new Long(countDownLatch.getCount()).intValue()];

        for (int i = 0; i < runnerSign.length; i++) {
            runnerSign[i] = new RunThread(countDownLatch);
            runnerSign[i].setName("00"+(i+1));
            runnerSign[i].start();
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("所有运动员都已经到现场了！");
    }
}

